package com.yzc.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzc.apis.logClient.MainOrderLogClient;
import com.yzc.execption.ZcException;
import com.yzc.mapper.TourMapper;
import com.yzc.model.entity.log.InventoryLog;
import com.yzc.model.entity.system.Tour;
import com.yzc.redis.RedisUtil;
import com.yzc.result.Result;
import com.yzc.service.TourService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.yzc.constant.RedisConstant.INVENTORY_DEDUCTION_LOG;
import static com.yzc.rabbit.OrderType.TRAVEL;


/**
 * @author Yzc
 * @description 针对表【t_tour】的数据库操作Service实现
 * @createDate 2024-06-13 15:28:57
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TourServiceImpl extends ServiceImpl<TourMapper, Tour>
        implements TourService {

    private final TourMapper tourMapper;
    private final Redisson redisson;
    private final MainOrderLogClient logClient;
    private final RedisUtil redisUtil;


    @Override
    public List<Tour> selectInfos(Tour tourname) {
        QueryWrapper<Tour> queryWrapper = new QueryWrapper<>();
        if (tourname != null && tourname.getTourname() != null) {
            String likeValue = "%" + tourname.getTourname() + "%";
            queryWrapper.like("tourname", likeValue);
        }
        return tourMapper.selectList(queryWrapper);
    }

    @Override
    public void deleteInfos(int tourid) {
        tourMapper.deleteById(tourid);
        tourMapper.updatePveList();
    }

    @Override
    public Tour getTourid(Integer tourid) {
        return tourMapper.selectById(tourid);
    }

    @Override
    public List<Tour> loadAllTourData() {
        return tourMapper.loadAllTourData();
    }

    @Override
    public String delProductUrl(Integer productId, String url, String urls) {
        return "";
    }

    @Override
    public void updateStock(Long attractionId, int ticketCount, Long orderId) {
        String lockKey = "tour:lock:" + attractionId + ":" + orderId; // 锁的 Key
        RLock redissonLock = redisson.getLock(lockKey); // 获取 Redisson 锁

        try {
            redissonLock.lock(10, TimeUnit.SECONDS);            // 设置锁的超时时间为 10 秒
            log.info("成功获取锁，景点ID:{}", attractionId);

            // 幂等性检查：是否已扣减
            String logCacheKey = INVENTORY_DEDUCTION_LOG + orderId+ ":" + attractionId;
            InventoryLog result = (InventoryLog) redisUtil.get(logCacheKey);
            if (result == null) {
                result = logClient.getInventoryLog(orderId).getData();
                redisUtil.set(logCacheKey, result, 600); // 缓存结果，过期时间为 10 分钟
            }
            if (result != null) {
                log.info("订单已扣减库存，跳过操作，订单ID: {}", orderId);
                return;
            }

            Tour tour = tourMapper.selectById(attractionId);
            if (tour == null) {
                throw new RuntimeException("未找到景点ID为 " + attractionId + " 的记录");
            }
            if (tour.getStock() + ticketCount < 0) {
                throw new RuntimeException("库存不足，景点ID: " + attractionId);
            }

            LambdaUpdateWrapper<Tour> stockLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            stockLambdaUpdateWrapper.eq(Tour::getTourid, attractionId)
                    .setSql("stock = stock + " + ticketCount);
            int rows = tourMapper.update(stockLambdaUpdateWrapper);
            if (rows == 0) {
                throw new RuntimeException("库存更新失败，景点ID: " + attractionId);
            }

            // 记录扣减日志
            InventoryLog inventoryLog = new InventoryLog();
            inventoryLog.setOrderId(orderId);
            inventoryLog.setStatus(TRAVEL.getCode());
            inventoryLog.setOperator("system");
            inventoryLog.setInventoryDeduction("景点ID:" + attractionId + " 扣减了" + Math.abs(ticketCount) + "张票");
            inventoryLog.setRemark("库存扣减操作");
            inventoryLog.setCreateTime(new java.util.Date());
            logInventoryAsync(inventoryLog); // 异步记录日志

            redisUtil.set(logCacheKey, inventoryLog, 600);

            log.info("库存更新成功，景点ID: {}", attractionId);
        } catch (ZcException e) {
            log.error("业务异常，景点ID: {}, 异常信息: {}", attractionId, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("系统异常，景点ID: {}, 异常信息: {}", attractionId, e.getMessage(), e);
            throw new RuntimeException("系统异常，景点ID: " + attractionId, e);
        } finally {
            if (redissonLock.isLocked() && redissonLock.isHeldByCurrentThread()) {
                redissonLock.unlock();
                log.info("释放锁成功，景点ID:{}", attractionId);
            }
        }
    }

    @Async
    public void logInventoryAsync(InventoryLog inventoryLog) {
        try {
            Result<Boolean> booleanResult = logClient.creatInventoryLog(inventoryLog);
            if (!booleanResult.getData()) {
                log.error("记录扣减日志失败，订单ID: {}", inventoryLog.getOrderId());
            }
        } catch (Exception e) {
            log.error("记录扣减日志异常，订单ID: {}", inventoryLog.getOrderId(), e);
        }
    }


}




